<?php

namespace PHPSpring\Web;

use PHPSpring\Annotation\Impl\Validation;
use PHPSpring\Core\RuntimeAnnotation;

trait ValidationRules {


  //public array $except = [];//子类中中指定黑名单entities（不允许出现在返回到前端的rules中）


  /**
   * 加载Entity校验规则 <br>
   * EG: /index/rules 返回全部Entity <br>
   * EG: /index/rules?entities=App\Entity\User 单个Entity <br>
   * EG: /index/rules?entities[]=App\Entity\User&entities[]=App\Entity\Group 返回多个Entity
   * @param array|string|null $entities 要获取的entities列表，为空为全部，EG: ['App\Entity\User']
   * @return array
   * @Get('/rules')
   */
  public function rules ($entities = null): array {
    $allAnnos = RuntimeAnnotation::getAnnotations();
    if (empty($allAnnos)) {
      return [];
    }

    if (empty($entities)) {
      $entities = [];
    } else {
      $entities = (array)$entities;
    }

    $rules = [];
    foreach ($allAnnos as $annoInfo) {
      $classFull = $annoInfo['class']['type'] ?? '';
      if (empty($classFull)) {
        //这里因为速度，并不去判断class_exists
        continue;
      }
      if (property_exists($this, 'except') && in_array($classFull, $this->except)) {
        continue;
      }
      if ($entities && !in_array($classFull, $entities)) {
        continue;
      }
      $annosOfClass = $annoInfo['class']['annos'] ?? [];
      if (array_key_exists('Entity', $annosOfClass)) {
        $className = $annoInfo['class']['name'] ?? '';
        if (empty($className)) {
          continue;
        }
        $entityRules = $this->getEntityRules($classFull);
        if (!empty($entityRules)) {
          $rules[$className] = $entityRules;
        }
      }
    }

    return $rules;
  }


  private function getEntityRules ($classFull): array {
    $entityRules = [];
    $allValidatorsOfClass = Validation::getValidators($classFull);
    foreach ($allValidatorsOfClass as $field => $v) {
      $type = $v['type'] ?? '';
      $validatorsOfFiled = $v['validators'] ?? [];
      foreach ($validatorsOfFiled as $oneValidator) {
        $vClassName = $oneValidator['0'] ?? '';
        if (empty($vClassName)) {
          continue;
        }
        $vRawParams = $oneValidator[1] ?? [];
        $sErrorMsg = $vClassName::normalizeArguments($vRawParams);
        if ($sErrorMsg) {//后端的字段验证配置信息不正确，这里忽略
          continue;
        }
        $classNameParts = explode('\\', $vClassName);
        $classBaseName = end($classNameParts);
        $entityRules[$field][] = [
          'name'   => $classBaseName,
          'params' => $vRawParams,
          'type'   => $type,
        ];
      }
    }

    return $entityRules;
  }

}
